package cn.codergege.demo.service

import cn.codergege.demo.dao.PersonRepository
import cn.codergege.demo.entity.Person
import cn.codergege.demo.entity.QPerson.person
import com.querydsl.core.types.Predicate
import org.springframework.batch.core.Job
import org.springframework.batch.core.JobParameters
import org.springframework.batch.core.JobParametersBuilder
import org.springframework.batch.core.launch.JobLauncher
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.cache.annotation.CacheConfig
import org.springframework.cache.annotation.CacheEvict
import org.springframework.cache.annotation.CachePut
import org.springframework.cache.annotation.Cacheable
import org.springframework.context.annotation.PropertySource
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Service

@CacheConfig(cacheNames = arrayOf("person"))
@Service
class PersonService {
   @Autowired
   lateinit var personRepository: PersonRepository

   /**
    *  计划任务方式启动 person batch job
    */
   @Autowired
   lateinit var jobLauncher: JobLauncher
   @Autowired
   @Qualifier("csv2MysqlPersonJob")
   lateinit var job: Job

   @Scheduled(cron = "\${csv.to.mysql.person.cron}")
   fun executeJob() {
      jobLauncher.run(job
          , JobParametersBuilder()
          .addLong("time", System.currentTimeMillis())
          // 使用了 triggerReader
          .addString("path2File", "f:/tmp/person.csv")
          .toJobParameters()
      )
   }

   /**
    * 缓存:
    *    1. @Cacheable 常用于查询
    *       默认 key :
    *          1) 没有参数, key = new SimpleKey();
    *          2) 1 个参数, key 等于这个参数
    *          3) 多个参数, key = new SimpleKey(多个参数)
    *    2. @CachePut 常用于更新, 将更新后的返回值缓存起来(同步更新缓存)
    *       使用 @CachePut(value = "person", key = "#result.id")
    *    3. @CacheEvict 常用于删除, 将删除的结果从缓存中删除
    */

   //   @Cacheable("person")
   @Cacheable
   fun findPersonById(id: Int): Person {
      println("查询 id 是 $id 的 person.")
      return personRepository.findById(id).get()
   }
   @CachePut(value = "person", key = "#result.id")
   fun updatePerson(person: Person): Person {
      return personRepository.saveAndFlush(person)
   }
   @CacheEvict(value = "person", key = "#id")
   fun deletePerson(id: Int) {
      personRepository.deleteById(id)
   }

   @Cacheable(value = "person")
   fun findPersons(name: String): List<Person>? {
      return personRepository.findByName(name)
   }

   fun findPersonsByGender(gender: Int): Iterable<Person>? {
      val predicate: Predicate = person.gender.eq(gender)
      return personRepository.findAll(predicate)
   }
}
